home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / lists / mint / l_0799 / 729 < prev    next >
Encoding:
Internet Message Format  |  1994-08-27  |  11.1 KB

  1. From: Torsten Scherer <itschere@techfak.uni-bielefeld.de>
  2. Subject: MiNT 1.09 security: revised f_delete() patch + more
  3. Date: Sat, 18 Dec 93 15:40:56 +0100
  4.         benni@phil15.uni-sb.de
  5. In-Reply-To: <9312171520.AA24380@suntopo.matups.fr>; from "Thierry Bousch" at Dec 17, 93 4:19 pm
  6.  
  7. Bonjour Thierry!
  8.  
  9. > Hmm, if you want to support the sticky bit, you must also patch the
  10. > f_rename() and f_rmdir() functions, because you shouldn't be allowed to
  11. > rename/move files and subdirectories of a sticky folder. (Otherwise, it
  12. > would be a big security hole: you could move files to a non-sticky
  13. > folder, and delete them.)
  14.  
  15.  So it wasn't directly wrong, but just incomplete. Thanx for this info,
  16. you're of course right! This should be fixed with this revised patch,
  17. which is again relative to the original code because:
  18.  
  19. 1) everyone should have made a backup before
  20. 2) everyone should know how to unpatch a previous patch
  21. 3) probably nobody has applied the old one anyway ;-)
  22.  
  23.  Now f_delete(), f_rename() and d_delete() are patched so that you may
  24. not do an operation you want if "the sticky bit is set, and you're not
  25. superuser, and the item doesn't belong to you, and - in addition to your
  26. ramfs - the directory doesn't belong to you."
  27.  
  28.  You could in any case change the filemode of the directory if it belongs
  29. to you and then do what you like, but it seems more logical and/or convenient
  30. to me to do it this way.
  31.  
  32.  I've also changed the d_setpath() call so that it is now no longer allowed
  33. to change to a directory you don't have permission to. Until now, you can
  34. _change_ to any directory you like, but maybe refused to read it later. So
  35. this isn't a big problem, but it looks to be a bit more un*x like. :-)
  36.  
  37.  Je yous souhaites un bon joel, un tres bien annee' nouvaux et peut-`etre
  38. aussi des bon vacances d'hiver, si vous aller faire du ski ou quelque
  39. chose comme ,ca.
  40.  
  41.  Oh no, my french... :-(
  42.  
  43. anyway, happy X-Mas and a jolly new year 4 all :-)
  44. TeSche
  45. --
  46. PS: If the above written looks weird, then that's probably because it _is_.
  47. WhoDunnIt: Torsten Scherer (Schiller, Tesche, ...)
  48. Where: Faculty of Technology, University of Bielefeld, Germany
  49. EMail: itschere@techfak.uni-bielefeld.de / tesche@hrz.uni-bielefeld.de
  50.  
  51. ======= cut cut cut =======
  52. diff -u5 ./dosdir.c ../my/dosdir.c
  53. --- ./dosdir.c    Fri Nov 19 15:34:12 1993
  54. +++ ../my/dosdir.c    Sun Dec 19 14:19:58 1993
  55. @@ -113,11 +113,11 @@
  56.      if (r) {
  57.          DEBUG(("Dcreate(%s): returning %ld", path, r));
  58.          return r;    /* an error occured */
  59.      }
  60.  /* check for write permission on the directory */
  61. -    r = dir_access(&dir, S_IWOTH);
  62. +    r = dir_access(&dir, S_IWOTH, 0);
  63.      if (r) {
  64.          DEBUG(("Dcreate(%s): access to directory denied",path));
  65.          release_cookie(&dir);
  66.          return r;
  67.      }
  68. @@ -124,10 +124,13 @@
  69.      r = (*dir.fs->mkdir)(&dir, temp1, DEFAULT_DIRMODE & ~curproc->umask);
  70.      release_cookie(&dir);
  71.      return r;
  72.  }
  73.  
  74. +/* tesche: delete a directory with respect of the sticky bit
  75. + */
  76. +
  77.  long ARGS_ON_STACK
  78.  d_delete(path)
  79.      const char *path;
  80.  {
  81.      fcookie parentdir, targdir;
  82. @@ -134,10 +137,11 @@
  83.      long r;
  84.      PROC *p;
  85.      int i;
  86.      XATTR xattr;
  87.      char temp1[PATH_MAX];
  88. +    short sticky_uid;
  89.  
  90.      TRACE(("Ddelete(%s)", path));
  91.  
  92.      r = path2cookie(path, temp1, &parentdir);
  93.  
  94. @@ -147,18 +151,17 @@
  95.          return r;
  96.      }
  97.  /* check for write permission on the directory which the target
  98.   * is located
  99.   */
  100. -    if ((r = dir_access(&parentdir, S_IWOTH)) != 0) {
  101. +    if ((r = dir_access(&parentdir, S_IWOTH, &sticky_uid))) {
  102.          DEBUG(("Ddelete(%s): access to directory denied", path));
  103.          release_cookie(&parentdir);
  104.          return r;
  105.      }
  106.  
  107.  /* now get the info on the file itself */
  108. -
  109.      r = relpath2cookie(&parentdir, temp1, NULL, &targdir, 0);
  110.      if (r) {
  111.  bailout:
  112.          release_cookie(&parentdir);
  113.          DEBUG(("Ddelete: error %ld on %s", r, path));
  114. @@ -167,10 +170,20 @@
  115.      if ((r = (*targdir.fs->getxattr)(&targdir, &xattr)) != 0) {
  116.          release_cookie(&targdir);
  117.          goto bailout;
  118.      }
  119.  
  120. +/* check for sticky bit */
  121. +    if ((sticky_uid >= 0) &&
  122. +        curproc->euid &&
  123. +        (sticky_uid != curproc->euid) &&
  124. +        (curproc->euid != xattr.uid)) {
  125. +        release_cookie(&targdir);
  126. +        release_cookie(&parentdir);
  127. +        return EACCDN;
  128. +    }
  129. +
  130.  /* if the "directory" is a symbolic link, really unlink it */
  131.      if ( (xattr.mode & S_IFMT) == S_IFLNK ) {
  132.          r = (*parentdir.fs->remove)(&parentdir, temp1);
  133.      } else if ( (xattr.mode & S_IFMT) != S_IFDIR ) {
  134.          DEBUG(("Ddelete: %s is not a directory", path));
  135. @@ -215,11 +228,10 @@
  136.      fcookie dir;
  137.      int drv = curproc->curdrv;
  138.      int i;
  139.      char c;
  140.      long r;
  141. -    XATTR xattr;
  142.  
  143.      TRACE(("Dsetpath(%s)", path));
  144.  
  145.      r = path2cookie(path, follow_links, &dir);
  146.  
  147. @@ -234,24 +246,16 @@
  148.              drv = c-'a';
  149.          else if (c >= 'A' && c <= 'Z')
  150.              drv = c-'A';
  151.      }
  152.  
  153. -    r = (*dir.fs->getxattr)(&dir, &xattr);
  154. -
  155. -    if (r < 0) {
  156. -        DEBUG(("Dsetpath: file '%s': attributes not found", path));
  157. +    if ((r = dir_access(&dir, S_IXOTH, 0))) {
  158. +        DEBUG(("Dsetpath(%s): not a directory or access denied", path));
  159.          release_cookie(&dir);
  160.          return r;
  161.      }
  162.  
  163. -    if (!(xattr.attr & FA_DIR)) {
  164. -        DEBUG(("Dsetpath(%s): not a directory",path));
  165. -        release_cookie(&dir);
  166. -        return EPTHNF;
  167. -    }
  168. -
  169.  /*
  170.   * watch out for symbolic links; if c:\foo is a link to d:\bar, then
  171.   * "cd c:\foo" should also change the drive to d:
  172.   */
  173.      if (drv != UNIDRV && dir.dev != curproc->root[drv].dev) {
  174. @@ -504,11 +508,11 @@
  175.      }
  176.  
  177.  /* check to see if we have read permission on the directory (and make
  178.   * sure that it really is a directory!)
  179.   */
  180. -    r = dir_access(&dir, S_IROTH);
  181. +    r = dir_access(&dir, S_IROTH, 0);
  182.      if (r) {
  183.          DEBUG(("Fsfirst(%s): access to directory denied (error code %ld)", path, r));
  184.          release_cookie(&dir);
  185.          return r;
  186.      }
  187. @@ -716,48 +720,88 @@
  188.          release_cookie(&fc);
  189.          return xattr.attr;
  190.      }
  191.  }
  192.  
  193. +/* tesche: delete a file with respect of the sticky bit
  194. + */
  195. +
  196.  long ARGS_ON_STACK
  197.  f_delete(name)
  198.      const char *name;
  199.  {
  200. -    fcookie dir;
  201. -    long r;
  202. -    char temp1[PATH_MAX];
  203. +    fcookie    dir, fc;
  204. +    long    r;
  205. +    char    temp1[PATH_MAX];
  206. +    XATTR    fxattr;
  207. +    short    sticky_uid;
  208.  
  209.      TRACE(("Fdelete(%s)", name));
  210.  
  211. -    r = path2cookie(name, temp1, &dir);
  212. -
  213. -    if (r) {
  214. -        DEBUG(("Fdelete: error %ld", r));
  215. +/* first, get the directory cookie */
  216. +    if ((r = path2cookie(name, temp1, &dir))) {
  217. +        DEBUG(("Fdelete(%s): directory not found", name));
  218.          return r;
  219.      }
  220.  
  221.  /* check for write permission on directory */
  222. -    r = dir_access(&dir, S_IWOTH);
  223. -    if (r) {
  224. -        DEBUG(("Fdelete(%s): write access to directory denied",name));
  225. -    } else {
  226. -/* BUG: we should check here for a read-only file */
  227. -        r = (*dir.fs->remove)(&dir,temp1);
  228. +    if (dir_access(&dir, S_IWOTH, &sticky_uid)) {
  229. +        DEBUG(("Fdelete(%s): write access to directory denied", name));
  230. +        release_cookie(&dir);
  231. +        return EACCDN;
  232.      }
  233. +
  234. +/* if (sticky) and not(superuser) and not(my_directory): need more checks */
  235. +    if ((sticky_uid >= 0) &&
  236. +        curproc->euid &&
  237. +        (sticky_uid != curproc->euid)) {
  238. +        if ((r = relpath2cookie(&dir, temp1, 0, &fc, 0))) {
  239. +            DEBUG(("Fdelete(%s): error %ld, perhaps file not found", name, r));
  240. +            release_cookie(&dir);
  241. +            return r;
  242. +        }
  243. +
  244. +    /* check ownership of the file */
  245. +        if ((r = (fc.fs->getxattr)(&fc, &fxattr))) {
  246. +            DEBUG(("Fdelete(%s): can't get file attributes", name));
  247. +            release_cookie(&fc);
  248. +            release_cookie(&dir);
  249. +            return r;
  250. +        }
  251. +
  252. +        if (curproc->euid != fxattr.uid) {
  253. +            DEBUG(("Fdelete(%s): write access to file denied", name));
  254. +            release_cookie(&fc);
  255. +            release_cookie(&dir);
  256. +            return EACCDN;
  257. +        }
  258. +
  259. +        release_cookie(&fc);
  260. +    } /* sticky */
  261. +
  262. +/* actually delete the file */
  263. +    if ((r = (*dir.fs->remove)(&dir,temp1)))
  264. +        DEBUG(("Fdelete(%s): error %ld", name, r));
  265. +
  266.      release_cookie(&dir);
  267. +
  268.      return r;
  269.  }
  270.  
  271. +/* tesche: rename/move a file with respect of the sticky bit
  272. + */
  273. +
  274.  long ARGS_ON_STACK
  275.  f_rename(junk, old, new)
  276.      int junk;        /* ignored, for TOS compatibility */
  277.      const char *old, *new;
  278.  {
  279.      fcookie olddir, newdir, oldfil;
  280.      XATTR xattr;
  281.      char temp1[PATH_MAX], temp2[PATH_MAX];
  282.      long r;
  283. +    short sticky_uid;
  284.  
  285.      UNUSED(junk);
  286.  
  287.      TRACE(("Frename(%s, %s)", old, new));
  288.  
  289. @@ -799,12 +843,21 @@
  290.          release_cookie(&newdir);
  291.          return EXDEV;    /* cross device rename */
  292.      }
  293.  
  294.  /* check for write permission on both directories */
  295. -    r = dir_access(&olddir, S_IWOTH);
  296. -    if (!r) r = dir_access(&newdir, S_IWOTH);
  297. +    if (!(r = dir_access(&olddir, S_IWOTH, &sticky_uid)))
  298. +        r = dir_access(&newdir, S_IWOTH, 0);
  299. +
  300. +/* check for sticky bit */
  301. +    if (!r &&
  302. +        (sticky_uid >= 0) &&
  303. +        curproc->euid &&
  304. +        (sticky_uid != curproc->euid) &&
  305. +        (xattr.uid != curproc->euid))    /* oldfil specs */
  306. +        r = EACCDN;
  307. +
  308.      if (r) {
  309.          DEBUG(("Frename(%s,%s): access to a directory denied",old,new));
  310.      } else {
  311.          r = (*newdir.fs->rename)(&olddir, temp2, &newdir, temp1);
  312.      }
  313. @@ -873,11 +926,11 @@
  314.      r = path2cookie(name, follow_links, &dir);
  315.      if (r) {
  316.          DEBUG(("Dopendir(%s): error %ld", name, r));
  317.          return r;
  318.      }
  319. -    r = dir_access(&dir, S_IROTH);
  320. +    r = dir_access(&dir, S_IROTH, 0);
  321.      if (r) {
  322.          DEBUG(("Dopendir(%s): read permission denied", name));
  323.          release_cookie(&dir);
  324.          return r;
  325.      }
  326. @@ -1042,11 +1095,11 @@
  327.          return EXDEV;    /* cross device link */
  328.      }
  329.  
  330.  /* check for write permission on the destination directory */
  331.  
  332. -    r = dir_access(&newdir, S_IWOTH);
  333. +    r = dir_access(&newdir, S_IWOTH, 0);
  334.      if (r) {
  335.          DEBUG(("Flink(%s,%s): access to directory denied",old,new));
  336.      } else
  337.          r = (*newdir.fs->hardlink)(&olddir, temp2, &newdir, temp1);
  338.      release_cookie(&olddir);
  339. @@ -1072,11 +1125,11 @@
  340.      r = path2cookie(new, temp1, &newdir);
  341.      if (r) {
  342.          DEBUG(("Fsymlink(%s,%s): error parsing %s", old,new,new));
  343.          return r;
  344.      }
  345. -    r = dir_access(&newdir, S_IWOTH);
  346. +    r = dir_access(&newdir, S_IWOTH, 0);
  347.      if (r) {
  348.          DEBUG(("Fsymlink(%s,%s): access to directory denied",old,new));
  349.      } else
  350.          r = (*newdir.fs->symlink)(&newdir, temp1, old);
  351.      release_cookie(&newdir);
  352. diff -u5 ./filesys.c ../my/filesys.c
  353. --- ./filesys.c    Fri Nov 19 15:34:22 1993
  354. +++ ../my/filesys.c    Sat Dec 18 14:41:38 1993
  355. @@ -1100,16 +1100,18 @@
  356.      return t;
  357.  }
  358.  
  359.  /*
  360.   * check to see that a file is a directory, and that write permission
  361. - * is granted; return an error code, or 0 if everything is ok.
  362. + * is granted; return an error code, or 0 if everything is ok. also return
  363. + * the uid of the directory if the sticky bit is set, or -1 otherwise,
  364.   */
  365.  long
  366. -dir_access(dir, perm)
  367. +dir_access(dir, perm, sticky_uid)
  368.      fcookie *dir;
  369.      unsigned perm;
  370. +    short *sticky_uid;
  371.  {
  372.      XATTR xattr;
  373.      long r;
  374.  
  375.      r = (*dir->fs->getxattr)(dir, &xattr);
  376. @@ -1122,10 +1124,16 @@
  377.          return EPTHNF;
  378.      }
  379.      if (denyaccess(&xattr, perm)) {
  380.          DEBUG(("no permission for directory"));
  381.          return EACCDN;
  382. +    }
  383. +    if (sticky_uid) {
  384. +        if (xattr.mode & S_ISVTX) {
  385. +            *sticky_uid = xattr.uid;
  386. +        } else
  387. +            *sticky_uid = -1;
  388.      }
  389.      return 0;
  390.  }
  391.  
  392.  /*
  393. diff -u5 ./proto.h ../my/proto.h
  394. --- ./proto.h    Fri Nov 19 15:34:38 1993
  395. +++ ../my/proto.h    Sat Dec 18 14:42:16 1993
  396. @@ -182,11 +182,11 @@
  397.  FILEPTR *new_fileptr P_((void));
  398.  void dispose_fileptr P_((FILEPTR *f));
  399.  int ARGS_ON_STACK denyshare P_((FILEPTR *list, FILEPTR *newfileptr));
  400.  int denyaccess P_((XATTR *, unsigned));
  401.  LOCK * ARGS_ON_STACK denylock P_((LOCK *list, LOCK *newlock));
  402. -long dir_access P_((fcookie *, unsigned));
  403. +long dir_access P_((fcookie *, unsigned, short *));
  404.  int has_wild P_((const char *name));
  405.  void copy8_3 P_((char *dest, const char *src));
  406.  int pat_match P_((const char *name, const char *template));
  407.  int samefile P_((fcookie *, fcookie *));
  408.  
  409.